//
//  NSString+Parameters.m
//  QTCategory
//
//  Created by 张俊博 on 2016/10/17.
//  Copyright © 2016年 CISDI. All rights reserved.
//

#import "NSString+Parameters.h"
#import "NSString+QTAdd.h"
#import "NSDictionary+Parameters.h"

@interface QTQueryStringPair : NSObject
@property (readwrite, nonatomic, strong) id field;
@property (readwrite, nonatomic, strong) id value;

- (instancetype)initWithField:(id)field value:(id)value;

- (NSString *)URLEncodedStringValue;
@end

@implementation QTQueryStringPair

- (instancetype)initWithField:(id)field value:(id)value {
    self = [super init];
    if (!self) {
        return nil;
    }
    
    self.field = field;
    self.value = value;
    
    return self;
}

- (NSString *)URLEncodedStringValue {
    if (!self.value || [self.value isEqual:[NSNull null]]) {
        return [self.field description].stringByRouterURLEncode;
    } else {
        return [NSString stringWithFormat:@"%@=%@", [self.field description].stringByRouterURLEncode, [self.value description].stringByRouterURLEncode];
    }
}

@end

FOUNDATION_EXPORT NSArray * QTQueryStringPairsFromDictionary(NSDictionary *dictionary);
FOUNDATION_EXPORT NSArray * QTQueryStringPairsFromKeyAndValue(NSString *key, id value);

NSString * QTQueryStringFromParameters(NSDictionary *parameters) {
    NSMutableArray *mutablePairs = [NSMutableArray array];
    for (QTQueryStringPair *pair in QTQueryStringPairsFromDictionary(parameters)) {
        [mutablePairs addObject:[pair URLEncodedStringValue]];
    }
    
    return [mutablePairs componentsJoinedByString:@"&"];
}

NSArray * QTQueryStringPairsFromDictionary(NSDictionary *dictionary) {
    return QTQueryStringPairsFromKeyAndValue(nil, dictionary);
}

NSArray * QTQueryStringPairsFromKeyAndValue(NSString *key, id value) {
    NSMutableArray *mutableQueryStringComponents = [NSMutableArray array];
    
    NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"description" ascending:YES selector:@selector(compare:)];
    
    if ([value isKindOfClass:[NSDictionary class]]) {
        NSDictionary *dictionary = value;
        // Sort dictionary keys to ensure consistent ordering in query string, which is important when deserializing potentially ambiguous sequences, such as an array of dictionaries
        for (id nestedKey in [dictionary.allKeys sortedArrayUsingDescriptors:@[ sortDescriptor ]]) {
            id nestedValue = dictionary[nestedKey];
            if (nestedValue) {
                [mutableQueryStringComponents addObjectsFromArray:QTQueryStringPairsFromKeyAndValue((key ? [NSString stringWithFormat:@"%@[%@]", key, nestedKey] : nestedKey), nestedValue)];
            }
        }
    } else if ([value isKindOfClass:[NSArray class]]) {
        NSArray *array = value;
        for (id nestedValue in array) {
            [mutableQueryStringComponents addObjectsFromArray:QTQueryStringPairsFromKeyAndValue([NSString stringWithFormat:@"%@[]", key], nestedValue)];
        }
    } else if ([value isKindOfClass:[NSSet class]]) {
        NSSet *set = value;
        for (id obj in [set sortedArrayUsingDescriptors:@[ sortDescriptor ]]) {
            [mutableQueryStringComponents addObjectsFromArray:QTQueryStringPairsFromKeyAndValue(key, obj)];
        }
    } else {
        [mutableQueryStringComponents addObject:[[QTQueryStringPair alloc] initWithField:key value:value]];
    }
    
    return mutableQueryStringComponents;
}

@implementation NSString (Parameters)

- (NSString *)appendingParams:(NSDictionary *)params {
    if (!params || params.count<=0) {
        return self;
    } else {
        return [NSString stringWithFormat:@"%@?%@", self, QTQueryStringFromParameters(params)];
    }
}


//- (NSString *)appendingParams:(NSDictionary *)params
//{
//    if (!params || params.count<=0) {
//        return self;
//    }
//    
//    NSMutableArray* pairs = [NSMutableArray array];
//    for (NSString* key in params.keyEnumerator) {
//        NSString* value = [NSString stringWithFormat:@"%@", [params objectForKey:key]];
//        NSString* escaped_value = (NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(NULL, /* allocator */
//                                                                                                        (CFStringRef)value,
//                                                                                                        NULL, /* charactersToLeaveUnescaped */
//                                                                                                        (CFStringRef)@"!*'();:@&=+$,/?%#[]",kCFStringEncodingUTF8));
//        [pairs addObject:[NSString stringWithFormat:@"%@=%@", key, escaped_value]];
//    }
//    NSString *query = [pairs componentsJoinedByString:@"&"];
//    return [NSString stringWithFormat:@"%@?%@", self, query];
//}

@end
